/************************************************************************/
/* Name : Kiwon Yun
/* Partner's name : Eric Rooney
/* File Name : main.cpp
/* The name of assignment : Iteration 2
/************************************************************************/

#include "Common.h"
#include "Dealer.h"
#include "Player.h"
#include <iostream>
#include <sstream>

using namespace std;

/** This is an text-based interactive terminal for interacting
* with a deck of cards. */
int main(int argc, char* argv[])
{
	char* strMode;
	char* strTestFileName = NULL;
	E_MODE mode = STANDARD_MODE;

	// If it exists a flag ('-sp' or '-t'), set a mode.
	if( argc > 1 )
	{
		strMode = argv[1];

		// standard mode
		if( !strcmp( strMode, "-sp" ) )
		{
			mode = STANDARD_MODE;
		}

		// test mode
		else if( !strcmp( strMode, "-t" ) )
		{
			mode = TEST_MODE;

			if( argc < 3 )
			{
				cout << "You have to input '-t' with a test file name. [eg. -t deck.dat]" << endl;
				exit(1);
			}

			strTestFileName = argv[2];
		}
		else
		{
			cout << "You input a wrong flag. It is only allowed '-sp' or '-t'." << endl;
			exit(1);
		}
	}

	string input = "";
	Dealer* pDealer = new Dealer;

	while ( input != "q" && input != "Q" )
	{
/*
		cout<<'\n'<<"Round: "<<GameInfo::GetObjPtr()->GetRound();   ///////////////////////////////////DELETE///////////
		if( GameInfo::GetObjPtr()->IsStartGame() == true )
		{
			cout<<"     Sub round: "<<pDealer->GetSubRoundNum()<<endl;   ///////////////////////////////////DELETE///////////
		}
*/
		cout << endl << "Input a command!";

		if( pDealer->GetPlayersNum() != 0 )
		{
			cout << " ( This is " << pDealer->GetCurPlayerName() << "'s turn. )" << endl;

			if( pDealer->GetSubRoundNum() != -1 )
			{
				if( pDealer->IsCanBet() )
					cout << "You can bet now : Raise(B), Call(C), Fold(F)" << endl;
				else
					cout << "You can exchange your cards : Discard(D), Pass(P)" << endl;
			}
		}
		else
		{
			cout << endl;
		}

		
		cin >> input;

		// new game
		if ( input == "n" || input == "N" )
		{
			// clear previous game
			pDealer->ClearGame();

			string strPlayerName = "q";

			string strPlayerNum = " ";
			int nTotalPlayers;
			bool bInputPlayerNum = false;

			do 
			{
				cout << "How many people will play in this game?" << endl; 
				cout << "(At most 6 Players can participate in each game.)" << endl;
				cout << "Input the number of players : ";

				cin >> strPlayerNum;
				nTotalPlayers = atoi(strPlayerNum.c_str());

				if( nTotalPlayers <= 0 || nTotalPlayers > 6 )
				{
					cout << "You have to input the number that is more than 0 and less than 6." << endl;
					bInputPlayerNum = false;
				}
				else
				{
					bInputPlayerNum = true;
				}

			} while( !bInputPlayerNum );

			int nPlayerNum = 1;
			while ( nTotalPlayers - nPlayerNum >= 0 )
			{
				// Ask for the name of the player
				cout << "Input a player's name [" << nPlayerNum << "] : ";
				cin >> strPlayerName;

				// add player in the game
				pDealer->AddPlayer( strPlayerName.c_str() );

				nPlayerNum++;
			}
						
			string strBetMoney = " ";
			int nBetMoney=0;
			cout<<"How much money would you like the players to start out with?"<<endl;
			cin>>strBetMoney;
			nBetMoney=atoi(strBetMoney.c_str());
			while(nBetMoney<10 || nBetMoney>999)
			{
			cout<<"Enter a value between 10 and 1000"<<endl;
			cin>>strBetMoney;
			nBetMoney=atoi(strBetMoney.c_str());
			}
			pDealer->SetBetMoney(nBetMoney);

			// create a new game
			pDealer->CreateGame( mode, strTestFileName );

			//set to active status
			GameInfo::GetObjPtr()->SetStartGame( true ); 

			cout << "Succeeded to initiate a game." << endl;

			if( pDealer->GetPlayersNum() != 0 )
			{
				pDealer->Ante();
			}
			else
			{
				cout << endl;
			}

		}

		// show hand
		else if ( input == "s" || input == "S" )
		{
			if( !GameInfo::GetObjPtr()->IsStartGame() )
			{
				cout << "You have to initiate a game at first." << endl
					<< "You can initiate a game if you input 'n' or 'N'." << endl;
			}
			else if( pDealer->GetHandsNum() == 0 )
			{
				cout << "There are no players who join in this game." << endl;
			}
			else
			{
				pDealer->ShowCurHand();
			}
		}

		// remaining in deck
		else if (input == "r" || input == "R" )
		{
			if( !GameInfo::GetObjPtr()->IsStartGame() )
			{
				cout << "You have to initiate a game at first." << endl
					<< "You can initiate a game if you input 'n' or 'N'." << endl;
			}
			else
			{
				cout<< "Size of deck: " << pDealer->GetRemaingCardNum() << endl;
			}
		}

		// pass
		else if (input == "p" || input == "P" )
		{
			if( GameInfo::GetObjPtr()->IsStartGame() == false )
			{
				cout<<"No game exists.  Input n or N to start a new game"<<endl;
			}
			else
			{
				if( !pDealer->IsCanBet() )
					pDealer->ProcessNextTurn();
				else
					cout<<"Cannot pass during this betting round"<<endl;
			}
		}

		// discard
		else if (input == "d" || input == "D" )
		{
			
			//This section looks for the input after d or D
			char* m_strExtraInput;
			string m_strTempExtraInput;
			
			getline(cin, m_strTempExtraInput);
			
			char seps[] = " \n"; 
			char *m_strToken;

			int m_nCard1 = 0, m_nCard2 = 0, m_nCard3 = 0, m_nCardTooMany=0;

			if( GameInfo::GetObjPtr()->IsStartGame()==false)
				cout<<"No game exists.  Input n or N to start a new game"<<endl;
			else
			{
				if( !pDealer->IsCanBet() )
				{
					m_strExtraInput = new char[ strlen( m_strTempExtraInput.c_str() ) ];
					strcpy( m_strExtraInput, m_strTempExtraInput.c_str() );

					m_strToken=strtok(m_strExtraInput, seps);

					if(m_strToken != NULL)
						m_nCard1 = atoi( m_strToken );
					else
						m_nCard1='9';

					m_strToken=strtok(NULL, seps);

					if(m_strToken != NULL)
						m_nCard2 = atoi( m_strToken );

					m_strToken=strtok(NULL, seps);

					if(m_strToken != NULL)
						m_nCard3 = atoi( m_strToken );

					m_strToken=strtok(NULL, seps);

					if(m_strToken != NULL)
						m_nCardTooMany=9;

					if(m_nCard1<0)
						m_nCard1=0;
					if(m_nCard2<0)
						m_nCard2=0;
					if(m_nCard3<0)
						m_nCard3=0;
					if(m_nCardTooMany<0)
						m_nCardTooMany=0;

					if(m_nCardTooMany != 0)
						cout<<"At least 1 input beyond the 3 acceptable inputs was ignored."<<endl;


					if( m_strExtraInput )
					{
						//delete m_strExtraInput;
						m_strExtraInput = NULL;
					}


					while((m_nCard1>5)||(m_nCard2>5)||(m_nCard3>5))
					{
						m_nCard1=0, m_nCard2=0, m_nCard3=0,m_nCardTooMany=0;//reset cards
						cout << "Only numbers 1-5!" << "\n";
						cout << "Please try again.  Format is: d # # # " << "\n";

						getline(cin, m_strTempExtraInput);

						m_strExtraInput = new char[ strlen( m_strTempExtraInput.c_str() ) ];
						strcpy( m_strExtraInput, m_strTempExtraInput.c_str() );

						m_strToken=strtok(m_strExtraInput, seps);

						if(m_strToken[0]=='d' || m_strToken[0]=='D')
						{
							m_strToken=strtok(NULL, seps);

							if(m_strToken != NULL)
								m_nCard1 = atoi( m_strToken );
							else
								m_nCard1=9;

							m_strToken=strtok(NULL, seps);

							if(m_strToken != NULL)
								m_nCard2 = atoi( m_strToken );

							m_strToken=strtok(NULL, seps);

							if(m_strToken != NULL)
								m_nCard3 = atoi( m_strToken );

							m_strToken=strtok(NULL, seps);

							if(m_strToken != NULL)
								m_nCardTooMany=9;

							if(m_nCard1<0)
								m_nCard1=0;
							if(m_nCard2<0)
								m_nCard2=0;
							if(m_nCard3<0)
								m_nCard3=0;

							if(m_nCardTooMany<0)
								m_nCardTooMany=0;

							if(m_nCardTooMany != 0)
								cout<<"At least 1 input beyond the 3 acceptable inputs was ignored."<<endl;
						}
						else
							m_nCard1=9;                        

						if( m_strExtraInput )
						{
							//delete m_strExtraInput;
							m_strExtraInput = NULL;
						}

					}

					cout<<"Selected: "<<m_nCard1<<" "<<m_nCard2;
					cout<<" "<<m_nCard3<<"\n";

					pDealer->Discard(m_nCard1,m_nCard2,m_nCard3);

					pDealer->ShowCurHand();  //show result of discard

					pDealer->ProcessNextTurn();
				}
				else
				{
					cout<<"Cannot discard during this betting round"<<endl;
				}
			}
		}
		
		// Call
		else if (input == "c" || input == "C" )
		{
			if(GameInfo::GetObjPtr()->IsStartGame() == false)
			{
				cout<<"No game exists.  Input n or N to start a new game"<<endl;
			}
			else if( !pDealer->IsCanBet() )
			{
				cout<<"Cannot call during this round"<<endl;
			}
			else
			{
				pDealer->Call();
				pDealer->ProcessNextTurn();
			}
		}
		
		// Show Money
		else if (input == "m" || input == "M" )
		{
			if( GameInfo::GetObjPtr()->IsStartGame() == false )
			{
				cout<<"No game exists.  Input n or N to start a new game"<<endl;
			}
			else
			{
				pDealer->ShowMoney();
			}
		}

		// Fold
		else if (input == "f" || input == "F" )
		{
			if( GameInfo::GetObjPtr()->IsStartGame() == false )
			{
				cout<<"No game exists.  Input n or N to start a new game"<<endl;
			}
			else if( pDealer->IsCanBet() )
			{
				pDealer->Fold();
				pDealer->ProcessNextTurn();
			}
			else
				cout<<"Cannot fold until last round of betting"<<endl;
		}

		// Raise
		else if (input == "b" || input == "B" )
		{
			//This section looks for the input after b or B
			char* m_strExtraInput;
			string m_strTempExtraInput;

			getline(cin, m_strTempExtraInput);

			char seps[] = " \n"; 
			char *m_strToken;

			int m_nAmount = 99999, m_nAmountTooMany=0;

			if(GameInfo::GetObjPtr()->IsStartGame()==false)
				cout<<"No game exists.  Input n or N to start a new game"<<endl;	
			else
			{
				if( pDealer->IsCanBet() )
				{
					if((pDealer->GetRaises()<3)||(pDealer->GetPlayersNum()==2))
					{
						m_strExtraInput = new char[ strlen( m_strTempExtraInput.c_str() ) + 1 ];
						strcpy( m_strExtraInput, m_strTempExtraInput.c_str() );

						m_strToken=strtok(m_strExtraInput, seps);

						if(m_strToken != NULL)
							m_nAmount = atoi( m_strToken );
						else
							m_nAmount=99999;

						m_strToken=strtok(NULL, seps);

						if(m_strToken != NULL)
							m_nAmountTooMany=99999;

						if(m_nAmount<1)
							m_nAmount=99999;
						if(m_nAmountTooMany<0)
							m_nAmountTooMany=0;

						if(m_nAmountTooMany != 0)
							cout<<"At least 1 input beyond the 1 acceptable inputs was ignored."<<endl;


						if( m_strExtraInput )
						{
							delete m_strExtraInput;
							m_strExtraInput = NULL;
						}


						int * m_pAmount=0;
						m_pAmount=&m_nAmount;
						bool m_bRaiseSuccess=false;
						pDealer->Raise(m_pAmount);

						while(*m_pAmount==99999)
						{   
							m_nAmountTooMany=0;

							cout << "Please try again.  Format is: b # to raise. To call, type c" << "\n";
							getline(cin, m_strTempExtraInput);
							m_strExtraInput = new char[ strlen( m_strTempExtraInput.c_str() ) + 1 ];
							strcpy( m_strExtraInput, m_strTempExtraInput.c_str() );

							m_strToken=strtok(m_strExtraInput, seps);

							if(m_strToken[0]=='b' || m_strToken[0]=='B')
							{
								m_strToken=strtok(NULL, seps);
								if(m_strToken != NULL)
									*m_pAmount = atoi( m_strToken );
								else
									*m_pAmount=99999;
								m_strToken=strtok(NULL, seps);
								if(m_strToken != NULL)
									m_nAmountTooMany=99999;
								if(*m_pAmount<0)
									*m_pAmount=99999;
								if(m_nAmountTooMany<0)
									m_nAmountTooMany=0;
								if(m_nAmountTooMany != 0)
									cout<<"At least 1 input beyond the 1 acceptable inputs was ignored."<<endl;
								if( m_strExtraInput )
								{
									delete m_strExtraInput;
									m_strExtraInput = NULL;
								}
								pDealer->Raise(m_pAmount);
							}
							else if(m_strToken[0]=='c' || m_strToken[0]=='C')
							{
								pDealer->Call();
								*m_pAmount=1;
							}
							else
								*m_pAmount=99999;
						}
						pDealer->ProcessNextTurn();
					}
					else
					{
						if(pDealer->GetRaises()>2)
							cout<<"Only three raises per round of betting."<<endl;
					}
				}
				else
				{
					cout<<"This is not a betting round."<<endl;
				}
			}
		}

		// help
		else if ( input == string("h") || input == string("H") )
		{
			cout<< "n or N - Initiates a game."<<endl;
			cout<< "s or S - Displays the contents of the players hand."<<endl;
			cout<< "r or R - Displays the number of cards remaining in the deck."<<endl;
			cout<< "q or Q - Quits the program."<<endl;
			cout<< "d or D - The player discards selected cards."<<endl;
			cout<< "p or P - Pass."<<endl;
			cout<< "b or B - Raise"<<endl;
			cout<< "c or C - Call"<<endl;
			cout<< "f or F - Fold"<<endl;
			cout<< "m or M - Show player's money"<<endl;
			cout<< "h or H - How meta!"<<endl;
		}

		// quit
		else if ( input == "q" || input == "Q" )
		{
			// don't need to any code.
		}
/*
		// for test
		else if ( input == "l" || input == "L" )
		{
			pDealer->ShowTestLog();
		}

		// for test
		else if( input == "z" )
		{
			pDealer->CalcRankScore();
		}
*/
		// bad command
		else
		{
			cout<<"No such command.  Enter h or H for help."<<"\n";
		}
	}

	if( pDealer )
	{
		delete pDealer;
		pDealer = NULL;
	}
}
